import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import aima.search.framework.Problem;
import aima.search.framework.Search;
import aima.search.framework.SearchAgent;
import aima.search.framework.TreeSearch;
import aima.search.informed.HillClimbingSearch;
import aima.search.informed.SimulatedAnnealingSearch;
import IA.Energia.Centrales;
import IA.Energia.Clientes;


public class Main {

	/**
	 * Programa principal
	 * @author Jose Luis Orta
	 * @author Marc Baro
	 * @author Sergi Aguilar
	 * @param args
	 */
	public static void main(String[] args) {
		List<List<String>> resultados = new ArrayList<List<String>>();
		List<IExperiment> experimentos = new ArrayList<IExperiment>();
		char tipoAlgoritmo;
		int solucionInicial = 0;
		boolean[] operadores = {false, false, false, false};
		int numreplicas;
		int[] tipocentrales = { 0, 0, 0 };
		double pgarantizados = 0.0f;
		double[] ptipos = { 0.0f, 0.0f, 0.0f };
		int penalizacion = 0;
		int numClientes = 0;
		int it = 0;
		int incIt = 1;
		int finIt = 10;
		int itP = 0;
		int incItP = 1;
		int finItP = 10;
		int k = 1;
		int inck = 1;
		int fink = 10;
		double lambda = 0.01f;
		double incLambda = 0.01f;
		double finLambda = 1.0f;
		int incPen = 0;
		int finPen = 0;
		boolean continua = true;
		String nombre;
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		int i = 0;
		while (continua) {
		try {
			penalizacion = 0;
			System.out.print("Nombre del experimento: ");
			nombre = in.readLine();
			System.out.print("Tipo algoritmo (Hill Climbing: H | Simulated: S | Experimento 5: 5):");
			tipoAlgoritmo = in.readLine().charAt(0);
			System.out.print("Operadores (put,delete,move,swap) separados por comas:");
			String operadoresSelec[] = in.readLine().split(",");
			for (String operadorSelec : operadoresSelec) {
				if (operadorSelec.trim().equals("put")) operadores[2] = true;
				else if (operadorSelec.trim().equals("delete")) operadores[1] = true;
				else if (operadorSelec.trim().equals("move")) operadores[0] = true;
				else if (operadorSelec.trim().equals("swap")) operadores[0] = true;
			}
			System.out.print("Numero de replicas:");
			numreplicas = Integer.parseInt(in.readLine());
			System.out.print("Solucion inicial (linear,random,greedy):");
			String solucionSelec = in.readLine();
			if (solucionSelec.equals("linear")) solucionInicial = 0;
			else if (solucionSelec.equals("random")) solucionInicial = 1;
			else if (solucionSelec.equals("greedy")) solucionInicial = 2;
			else if (solucionSelec.equals("empty")) solucionInicial = 3;
			else if (solucionSelec.equals("empty")) solucionInicial = 4;
			System.out.print("Numero de clientes:");
			numClientes = Integer.parseInt(in.readLine());
			System.out.print("Cantidades de cada tipo de central separadas por comas:");
			String centralesTipos[] = in.readLine().split(",");
			for (i = 0; i < centralesTipos.length; i++) {
				tipocentrales[i] = Integer.parseInt(centralesTipos[i].trim());
			}
			if (i < 3) throw new Exception("Numero de tipos de centrales incorrecto");
			System.out.print("Porcentaje de clientes garantizados:");
			pgarantizados = Double.parseDouble(in.readLine());
			System.out.print("Porcentaje de cada tipo de clientes:");
			String ptiposSelec[] = in.readLine().split(",");
			for (i = 0; i < ptiposSelec.length; i++) {
				ptipos[i] = Double.parseDouble(ptiposSelec[i].trim());
			}
			if (i < 3)  throw new Exception("Porcentaje de tipos de clientes incorrecto");
			System.out.print("Permitir solucion parcial? (S/N): ");
			if (in.readLine().equals("S")){
				System.out.print("Penalizacion solucion parcial: ");
				String penalSelec = in.readLine();
				penalizacion = Integer.parseInt(penalSelec);
			}
			if(tipoAlgoritmo == 'S') {
				System.out.print("Simulated annealing: Iteraciones: valor, incremento y final separados por comas:");
				String valoresHit[] = in.readLine().split(",");
				it = Integer.parseInt(valoresHit[0].trim());
				incIt = Integer.parseInt(valoresHit[1].trim());
				finIt = Integer.parseInt(valoresHit[2].trim());
				
				System.out.print("Simulated annealing: Iteraciones por cada paso de temperatura: valor, incremento y final separados por comas:");
				String valoresHitp[] = in.readLine().split(",");
				itP = Integer.parseInt(valoresHitp[0].trim());
				incItP = Integer.parseInt(valoresHitp[1].trim());
				finItP = Integer.parseInt(valoresHitp[2].trim());
				
				System.out.print("Simulated annealing: K: valor, incremento y final separados por comas:");
				String valoresHk[] = in.readLine().split(",");
				k = Integer.parseInt(valoresHk[0].trim());
				inck = Integer.parseInt(valoresHk[1].trim());
				fink = Integer.parseInt(valoresHk[2].trim());
				
				System.out.print("Simulated annealing: Lambda: valor, incremento y final separados por comas:");
				String valoresHl[] = in.readLine().split(",");
				lambda = Double.parseDouble(valoresHl[0].trim());
				incLambda = Double.parseDouble(valoresHl[1].trim());
				finLambda = Double.parseDouble(valoresHl[2].trim());
			}
			
			if(tipoAlgoritmo == '5') {
				System.out.print("Experimento 5, simulated: Iteraciones, Iteraciones por cada paso, k y lambda separados porcomas:");
				String valoresH5[] = in.readLine().split(",");
				it = Integer.parseInt(valoresH5[0].trim());
				itP = Integer.parseInt(valoresH5[1].trim());
				k = Integer.parseInt(valoresH5[2].trim());
				lambda = Double.parseDouble(valoresH5[3].trim());
				System.out.print("Incremento y final de penalizacion separados por comas: "); 
				String valoresP[] = in.readLine().split(",");
				incPen = Integer.parseInt(valoresP[0].trim());
				finPen = Integer.parseInt(valoresP[0].trim());
			}

			switch (tipoAlgoritmo) {
			case 'H':
				IExperiment exp1 = new Experimento1(nombre, operadores, numreplicas, solucionInicial, numClientes, tipocentrales, pgarantizados, ptipos, penalizacion);
				experimentos.add(exp1);
				break;
			case 'S':
				IExperiment exp2 = new Experimento3(nombre, operadores, numreplicas, solucionInicial, numClientes, tipocentrales, pgarantizados, ptipos, it, incIt, finIt, itP, incItP, finItP, k, inck, fink, lambda, incLambda, finLambda);
				experimentos.add(exp2);
				break;
			case '5':
				IExperiment exp3 = new Experimento5(nombre, operadores, numreplicas, solucionInicial, numClientes, tipocentrales, pgarantizados, ptipos, it, itP, k, lambda, penalizacion, incPen, finPen);
				experimentos.add(exp3);
				break;
			}
			
			System.out.print("Mas experimentos? (S/EOF):");
			continua = in.readLine().equals("EOF") ? false : true;
			} catch (Exception e) {
			System.out.print("Parametro incorrecto: ");
			// TODO Auto-generated catch block
			System.out.println(e.getMessage());
			}
			
		}
		
		System.out.println("Experimentos");
		for (IExperiment exp : experimentos) {
			exp.execute();
			resultados.addAll(exp.getResult());
		}
		
		for (List<String> resultado : resultados) {
			boolean first = true;
			for (String valor : resultado) {
				if (first) first = false;
				else System.out.print(";");
				System.out.print(valor);
			}
			System.out.println();
		}
		//new Experimento4().execute();
	}
}
